#ifndef __thinvm_mmu__
#define __thinvm_mmu__

#include "thinvm.h"

namespace thinvm
{
	struct mmu_page_desc_t : refable_impl_t
	{
		uint32_t				attr;		// VMPA_READ|VMPA_WRITE|VMPA_EXEC|mem_moa|mem_hook|
		void*					data;
		uint16_t				icic;		// in cache instruction count
		uint16_t				dirty:1;
		mmu_page_desc_t() : attr(0), data(0), icic(0), dirty(0)
		{}
	};

	struct mmu_t
	{
		struct fast_entry_t
		{
			uint32_t			base;
			mmu_page_desc_t*	desc;
			fast_entry_t() : base(-1), desc(0){}
		};

		typedef std::map<uint32_t,refp<mmu_page_desc_t> > mmu_map_t;

		enum { FIX_SLOTS = 0x2000 };

		mmu_map_t			_slow_map;
		fast_entry_t		_fast_map[FIX_SLOTS];
		fast_entry_t		_last_read;
		fast_entry_t		_last_write;
		fast_entry_t		_last_exec;

		static inline void __invalid_fast_entry( fast_entry_t& entry )
		{
			entry.base = -1;
			entry.desc = 0;
		}

		void clear();

		mmu_page_desc_t *	mm_query_page( uint32_t addr, uint32_t acc = 0 );
		long				mm_map( uint32_t addr, uint32_t attr, void * host, size_t force = 0 );
		long				mm_unmap( uint32_t addr );

	protected:

		// callbacks
		virtual long		on_host_page_unuse( uint32_t addr, mmu_page_desc_t * desc );
		virtual long		impl_map_on_access( uint32_t addr, mmu_page_desc_t * desc );

		// tools
		mmu_page_desc_t *	__rwe_fast_find( uint32_t page_base, uint32_t acc );
		void				__rwe_pin( uint32_t page_base, mmu_page_desc_t * desc, uint32_t acc );
		void				__rwe_invalid( uint32_t page_base, uint32_t acc );
		void				__fast_map_invalid( uint32_t page_base );
		mmu_page_desc_t *	__load_slow_to_fast( uint32_t addr );


	};
	
};


#endif